home *** CD-ROM | disk | FTP | other *** search
- /*
- Paper Juggling, written by Dave Johnson
-
-
- This program implements a sort of "active graph paper" for messing with
- multi-person juggling patterns. See The Veteran Neophyte in develop
- magazine issue 22 for an explanation of juggling patterns in general and
- this notation in particular. Keep reading for implementation details.
-
- This program is hacked together for fun, and should not be considered a good
- example of anything.
-
- -----------------------------------------
- !! Use at your own (considerable) risk !!
- -----------------------------------------
-
- •GX Strategy:
-
- A lot of the general-purpose GX-specific code (printing, etc.) is stolen directly
- from the GXShell sample by Dave Hersey and Pete "Luke" Alexander.
-
- There are four picture objects that contain all the application-specific
- graphical objects:
- -One contains the dashed separator lines.
- -Another contains each of the jugglers in the pattern (each juggler is in turn
- a picture containing several "hands," which are just "L" or "R" text shapes).
- -Another contains all the primary throws (arrows).
- -The last one contains all the "faded" throws.
-
- There is one more picture object that contains the separatorsm jugglers, and
- primary throws, used mostly for printing and for one-step drawing during updates.
-
- The throw shapes use an ink that draws in xor mode, this is handy for fast erasing
- and redrawing without disturbing underlying bits. (Thank goodness for the transfer
- mode library and the SetInkFastXorTransfer routine.) Unfortunately that routine
- works on only one device at a time (see Known Deficiencies below).
-
- The faded throw shapes are drawn simultaneously into two separate viewports, which
- is how the ones that "wrap" are drawn in two places at once while dragging. Spiffy.
-
- Many more piddling details are discussed in the declarations below and in the code
- itself.
-
- •Known Deficiencies:
-
- Printing isn't great, though it's there. The problem is that the faded throws don't
- print, since they're drawn into different viewports.
-
- Multiple Monitor support is non-existent. This wouldn't be too hard to fix: make a
- separate ink for each monitor, and use DeviceLoop to figure out which one to use on
- the fly.
-
- •Known Bugs:
-
- Too many to tell you about them all... :-)
-
- */
-
- #include "Shell.h"
- // #include "AppInterface.h"
-
-
-
- //------------------------------
- // Constants
-
- // Colors
- #define kBGColor white
- #define kSeparatorColor black
- #define kArrowColor red
- #define kHandColor blue
- #define kLabelColor black
-
- // Distances and other constant numbers
- #define kArrowHeadLength ff(4)
- #define kArrowHeadHeight ff(4)
- #define kArrowPenSize ff(3)
-
- #define kDefaultGridSpace ff(48) // Grid spacing
- #define kDefaultJugglers 2 // Number of jugglers
- #define kDefaultCounts 6 // Number of time steps (hands per juggler)
- #define kMaxJugglers 20 // Maximum number of jugglers
- #define kMaxCounts 72 // Maximum number of counts (arbitrary, really, but any more would be unreasonable :-)
- #define kNumVSeparators 3 // number of vertical separators
- #define kHandTextSize (ff(16))
- #define kLabelTextSize (ff(9))
- #define kThrowDetent (ff(18)) // distance from which a throw "leaps" to the hand
- #define kHandRadius (ff(8)) // The distance a point can be away from the center of a hand
- // and still be considered inside it, used for fast hit testing
- // and for offsetting a throw's coords
-
-
- // Resources
- #define kThumbCursorID 128
- // #define kTimeSlipCursorID 129 // Someday I'll use this
-
- // File constants
- #define kJuggleFileType 'JUGL'
- #define kJuggleCreatorType 'JUGL'
-
- // Dialog resource ids and item numbers
- #define kJuggleSizeDialogId 130
- //#define iOKButton 1 // these are already defined in DialogUtils.h
- //#define iCancelButton 2
- //#define iOutline 3
- #define iNumJugglers 4 // The number of jugglers text item
- #define iNumCounts 5 // The number of counts text item
-
- // Menus and menu items
- #define kNumAppMenus 1
-
- #define kJuggleMenuID 131
- #define iResizeJuggle 1
- #define iAddJuggler 2
-
- // location in the global menu handle array
- #define kJuggleMenu 0
-
-
- //------------------------------
- // Macros
-
- #define fixAbs(a) ((a < 0) ? -a : a)
-
- //-------------------------------
- // Types
-
- // A HandLoc is much like a point, and specifies a particular hand location in the
- // array in memory.
- // (Note that this does not necessarily correspond to any particular position on
- // screen, since jugglers can be rearranged - i.e. juggler 1 may be three rows down)
- // Values are always positive (1-based) - zero signifies "none"
- typedef struct HandLoc
- {
- short time;
- short juggler;
- }HandLoc, *HandLocPtr;
-
- // A Hand is just a pair of HandLocs, specifying the source and sink for the hand.
- // In a "complete" pattern, every hand must have BOTH a source and a sink
- typedef struct Hand
- {
- HandLoc source;
- HandLoc sink;
- } Hand, *HandPtr, **HandHandle;
-
- /* This structure represents each "document". The FSSpec is used to keep track of whether
- a Save command should call Save As, and if not which file to save into. The dirty
- flag is used to keep track of when saving is necessary. The scroll bars are the scroll
- bars. the contentSize is the size of the document, in pixels. The Juggle stuff is the
- juggle stuff. */
- typedef struct
- {
- // Standard shell stuff
- Point contentSize;
- ControlHandle hScroll;
- ControlHandle vScroll;
- FSSpec fileSpec;
- Boolean dirty;
-
- // Standard GX stuff
- gxJob docJob; // print job for this document.
- gxShape docPage; // page shape description.
- gxViewPort docPort; // The child of the window's view port, used for scrolling
-
- // The Juggle
-
- // ----• Graphics stuff •----
-
- // The faded view ports
- gxViewPort afterPort; // the view port for drawing ghost throws to the right
- // of the main hands
- gxViewPort beforePort; // the view port for drawing ghost throws that come in
- // from the left to the main hands.
-
- // The shapes
- gxShape jugglersPict; // picture containing the jugglers
- gxShape throwsPict; // picture containing all the throws (arrows)
- gxShape fadedThrowsPict;// picture containing all the ghost throws
- gxShape sepsPict; // picture containing all the separator lines in the juggle
-
- // ----• Non-graphics stuff •----
-
- // An array of shorts used to map position on screen to the actual juggler row in memory.
- // Position in the array corresponds to position on screen, the value of an array slot
- // is the row of the juggler occupying that position on screen.
- short jugglerMap[kMaxJugglers];
-
-
- // State variables
- gxPoint gridPt; // The grid spacing in 72nds of an inch
- short numJugglers; // number of jugglers (rows)
- short numCounts; // number of time steps (columns)
-
- // The connections data is a 2D array of hands. How big the array is
- // will vary depending on the number of jugglers and the number of time
- // steps. How the hands are linked up (the pattern itself)
- // is determined by the data in the Hands.
- HandHandle theThrows;
-
- }DocumentRecord, *DocPeek, **DocHandle, Juggle, *JugglePointer, **JuggleHandle;
-
-
- //------------------------------
- // Prototypes
-
- // ----• JuggleRoutines.c •----
-
- // Init and CleanUp
- OSErr InitJuggle(WindowPtr wind, short numJugglers, short numCounts);
- void CleanUpJuggle(WindowPtr window, Boolean graphicsToo);
-
- // accessor routines for the juggle stuff in the window
- DocHandle GetWindowDoc(WindowPtr wind);
- JuggleHandle GetWindowJuggle(WindowPtr wind);
-
- // throw manipulation routines
- Boolean ResizeThrows(JuggleHandle aJuggle, short numJugglers, short numCounts,
- Boolean copyThrows);
- HandPtr GetHandPtr(HandHandle throws, short numCounts, short juggler, short count);
- HandPtr GetHand(JuggleHandle aJuggle, HandLoc theLoc, Boolean wrapIt);
- HandPtr GetIndexedHand(JuggleHandle aJuggle, short time, short juggler,
- Boolean wrapIt);
-
- void AddThrow(JuggleHandle aJuggle, HandLoc from, HandLoc to);
- void AddIndexedThrow(JuggleHandle aJuggle,
- short fromTime, short fromJuggler,
- short toTime, short toJuggler );
-
- void RemoveThrow(JuggleHandle aJuggle, HandLoc from, HandLoc to);
- void RemoveIndexedThrow(JuggleHandle aJuggle,
- short fromTime, short fromJuggler,
- short toTime, short toJuggler );
-
- void ClearJugglerThrows(JuggleHandle aJuggle, short juggler);
- void CopyThrows(HandHandle oldThrows, short oldJugglers, short oldCounts,
- HandHandle newThrows, short newJugglers, short newCounts);
- HandLoc FindReceiver(JuggleHandle aJuggle, HandLoc from);
-
- // routines that handle jugglers
- void MoveJuggler(JuggleHandle aJuggle, short whichJuggler, short offset);
- Boolean AddJuggler(JuggleHandle aJuggle);
- WindowPtr ResizeJuggle(WindowPtr wind);
-
-
- // ----• JuggleGraphics.c •----
-
- // initialization and clean up
- void InitCommonGraphicObjects(void);
- void KillCommonGraphicObjects(void);
-
- // shape creation
- gxShape MakeThrowShape(JuggleHandle aJuggle, Boolean faded);
- gxShape MakeHandShape(Boolean rightHand, Boolean faded);
- gxShape MakeLabelShape(short jugglerNumber);
- gxShape MakeSeparatorShape(JuggleHandle aJuggle, Boolean isHoriz);
- gxShape MakeJugglerShape(JuggleHandle aJuggle, Boolean rightFirst, short jugglerNumber);
- gxShape MakePrintingShape(JuggleHandle aJuggle);
- OSErr SetUpJuggleViewPorts(WindowPtr window, JuggleHandle aJuggle);
- gxShape SetUpJuggleGraphics(WindowPtr window, JuggleHandle aJuggle);
- void CleanUpJuggleShapes(WindowPtr window);
-
- // Graphics utilities
- void AddNewThrowShape(JuggleHandle aJuggle, gxLine *line, Boolean draw);
- void RemoveThrowShape(JuggleHandle aJuggle, short index);
- void MoveThrowShape(JuggleHandle aJuggle, short shapeIndex, gxLine *newLine);
- void RebuildThrowsPict(JuggleHandle aJuggle);
-
- void MoveJugglerInPict(JuggleHandle aJuggle, short fromRow, short toRow);
- void SwitchJugglerHands(JuggleHandle aJuggle, short index);
- void ChangeJugglerLabel(JuggleHandle aJuggle, short juggler, short newId);
-
- void SetDeepShapeInk(gxShape sh, gxInk ink);
- RgnHandle GetShapeBoundsRgn(gxShape juggler);
- Rect* GetShapeBoundsQDRect(gxShape shape, Rect *rect);
- Point GetQDWindowOrigin(WindowPtr window);
-
- void SetShapeFadePorts(JuggleHandle aJuggle, gxShape shape);
- void SetShapeMainPort(JuggleHandle aJuggle, gxShape shape);
- void SetInkBlendMode(gxInk theInk, short percent);
-
- void ResetJuggleContentSize(JuggleHandle aJuggle);
-
- // Accessors
- gxShape GetDocThrowsPict(WindowPtr wind);
- gxShape GetDocFadedThrowsPict(WindowPtr wind);
-
- // ----• JuggleInterface.c •----
-
- // mouse handling routines
- void DoJuggleClick(WindowPtr window, Point p, EventRecord *event);
- void DragJuggler(WindowPtr window, gxShape jugglerPict, gxPoint *clickPt,
- short whichJuggler, short constraint);
- void DragNewThrow(WindowPtr window, gxPoint *from);
- void DragThrow( JuggleHandle aJuggle,
- long shapeIndex,
- long whichPoint,
- gxPoint *from );
- Point DragGrayRgnGridded( RgnHandle theRgn,
- Point startPt,
- Rect *limitRect,
- Rect *slopRect,
- short axis,
- Point grid,
- Point *initialOffset);
- void KeepPtInBounds(JuggleHandle aJuggle, gxPoint *goodPt);
-
- // grid enforcement
- void GetGridOffset(gxPoint *pointData, gxPoint *grid);
- void GetShortGridOffset(Point *pointData, Point grid);
- Boolean Detent(gxPoint *pointData, gxPoint *grid, Fixed detentLimit);
- void SetGridPos(gxPoint *pointData, gxPoint *grid);
-
- // Screen conversion routines
- void MoveJugglerInMap(JuggleHandle aJuggle, short whichJuggler,
- short fromRow, short toRow);
- short JugglerToRow(JuggleHandle aJuggle, short juggler);
- short RowToJuggler(JuggleHandle aJuggle, short row);
- void HandLocToPoint(JuggleHandle aJuggle, HandLoc *hand, gxPoint *point);
- void PointToHandLoc(JuggleHandle aJuggle, gxPoint *point, HandLoc *hand,
- Boolean wrapIt);
- HandPtr PointToHand(JuggleHandle aJuggle, gxPoint *point, Boolean wrapIt);
-
- void LineToAddedThrow(JuggleHandle aJuggle, gxLine *line);
- void LineToRemovedThrow(JuggleHandle aJuggle, gxLine *line);
-
- // Dialog routines
- void DoJuggleSizeDialog(short *numCounts, short *numJugglers);
- Boolean JuggleSizeOK(DialogPtr dptr);
-
-
- // String utility routines, from DTS
- short clen(char *cptr);
- char* ccat(char *s1, char *s2);
- char* ccpy(char *s1, char *s2);
- void p2c(StringPtr cptr);
-
- // utils
- short min(short a, short b);
-
- // ----• JuggleFiles.c •----
- OSErr SaveJuggle(JuggleHandle aJuggle);
- OSErr JuggleToExistingFile(FSSpec *fileSpec, JuggleHandle aJuggle);
- OSErr JuggleToNewFile(FSSpec *fileSpec, JuggleHandle aJuggle);
- OSErr WriteJuggleToFile(FSSpec *fileSpec, JuggleHandle aJuggle);
- OSErr OpenJuggleFile(FSSpec *fileSpec, WindowPtr *wind);
-
-